package ai

import (
	"encoding/json"
	"fmt"
	"project-info/src/handle/mcp"
	"project-info/src/handle/response"
	"project-info/src/model"
	"strings"

	"project-info/src/lib")

// AI请求结构
type AIRequest struct {
	Message string `json:"message" binding:"required"` // 用户输入的消息
}

// AI响应结构
type AIResponse struct {
	Message         string                   `json:"message"`           // AI回复的消息
	Action          string                   `json:"action"`            // 执行的操作
	Parameters      map[string]interface{}   `json:"parameters"`        // 操作参数
	Executed        bool                     `json:"executed"`          // 是否已执行
	Result          *mcp.MCPToolResult       `json:"result"`            // 执行结果
	AvailableTools  []mcp.MCPTool            `json:"available_tools"`   // 可用工具列表
	ToolsByCategory map[string][]mcp.MCPTool `json:"tools_by_category"` // 按分类的工具列表
}

// OpenAI API请求结构
type OpenAIRequest struct {
	Model          string        `json:"model"`
	Messages       []Message     `json:"messages"`
	MaxTokens      int           `json:"max_tokens"`
	Temperature    float64       `json:"temperature"`
	EnableThinking bool          `json:"enable_thinking"`
	Tools          []mcp.MCPTool `json:"tools"`
}

type Message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

// OpenAI API响应结构
type OpenAIResponse struct {
	Choices []Choice `json:"choices"`
}

type Choice struct {
	Message Message `json:"message"`
}

// AI聊天处理器（集成统一的MCP工具管理器）
func AIChat(c *lib.GinContext) error {
	var req AIRequest
	if err := c.Bind(&req); err != nil {
		c.Logger().Error("参数错误：" + err.Error())
		return response.JsonFail(c, "参数错误")
	}

	// 创建MCP内部客户端
	mcpClient := mcp.NewMCPInternalClient(c)
	availableTools := mcpClient.GetAvailableTools()
	// toolsByCategory := mcpClient.GetToolsByCategory()

	// 构建系统提示词（包含MCP工具信息）
	systemPrompt := buildSystemPromptWithMCP(availableTools)

	// 调用AI模型
	aiResponse, err := callAIModel(req.Message, systemPrompt)
	if err != nil {
		c.Logger().Error("调用AI模型失败：" + err.Error())
		return response.JsonFail(c, "AI服务暂时不可用")
	}

	// 构建响应
	result := &AIResponse{
		Message:        aiResponse,
		AvailableTools: availableTools,
		// ToolsByCategory: toolsByCategory,
	}

	// 解析AI响应中的工具调用指令
	action, params := parseAIResponseForMCP(aiResponse)
	if action != "" {
		result.Action = action
		result.Parameters = params

		// 使用统一的工具管理器执行工具
		toolResult := mcpClient.CallTool(action, params)
		result.Result = toolResult
		result.Executed = toolResult.Success

		if toolResult.Success {
			result.Message += "\n\n" + toolResult.Content
		} else {
			result.Message += "\n\n执行操作时出现错误：" + toolResult.Error
		}
	}

	// 保存对话历史（可选）
	go saveAIChatHistory(c, req.Message, result)

	return response.JsonOk(c, result, "处理成功")
}

// 构建包含MCP工具信息的系统提示词
func buildSystemPromptWithMCP(tools []mcp.MCPTool) string {
	toolDescriptions := make([]string, 0, len(tools))
	for _, tool := range tools {
		toolDescriptions = append(toolDescriptions, fmt.Sprintf("- %s: %s", tool.Name, tool.Description))
	}

	return fmt.Sprintf(`你是一个智能运维助手，可以帮助用户管理和操作项目信息系统。

你可以使用以下工具来完成用户的请求：
%s

当你需要使用工具时，请在回复的最后添加：
TOOL_CALL: tool_name
TOOL_PARAMS: {"param1": "value1", "param2": "value2"}

工具调用规则：
1. 只有在用户明确需要执行某个操作时才调用工具
2. 参数必须是有效的JSON格式
3. 优先使用用户提供的具体参数
4. 如果用户没有提供必要参数，请询问用户
5. 选择最合适的工具来完成任务

请用中文回复，保持专业和友好的语调。`, strings.Join(toolDescriptions, "\n"))
}

// 调用AI模型（HTTP接口使用）
func callAIModel(userMessage, systemPrompt string) (string, error) {
	reqBody := OpenAIRequest{
		Model: model.C.AI.Model,
		Messages: []Message{
			{Role: "system", Content: systemPrompt},
			{Role: "user", Content: userMessage},
		},
		MaxTokens:   model.C.AI.MaxTokens,
		Temperature: model.C.AI.Temperature,
	}

	return callAIModelWithRequest(reqBody)
}

// 解析AI响应中的MCP工具调用指令
func parseAIResponseForMCP(response string) (string, map[string]interface{}) {
	lines := strings.Split(response, "\n")
	var toolName string
	var params map[string]interface{}

	for i, line := range lines {
		if strings.HasPrefix(line, "TOOL_CALL:") {
			toolName = strings.TrimSpace(strings.TrimPrefix(line, "TOOL_CALL:"))
		}
		if strings.HasPrefix(line, "TOOL_PARAMS:") {
			paramsStr := strings.TrimSpace(strings.TrimPrefix(line, "TOOL_PARAMS:"))
			if err := json.Unmarshal([]byte(paramsStr), &params); err != nil {
				// 如果解析失败，尝试下一行
				if i+1 < len(lines) {
					if err := json.Unmarshal([]byte(lines[i+1]), &params); err != nil {
						params = make(map[string]interface{})
					}
				}
			}
		}
	}

	return toolName, params
}

// 保存AI对话历史
func saveAIChatHistory(c *lib.GinContext, message string, response *AIResponse) {
	// 这里可以实现保存对话历史的逻辑
	history := &model.AIChatHistory{
		// UserId:   getUserIdFromContext(c), // 需要实现获取用户ID的逻辑
		Message:  message,
		Response: response.Message,
		Action:   response.Action,
		Executed: response.Executed,
	}

	if err := model.DB().Create(history).Error; err != nil {
		c.Logger().Error("保存对话历史失败: " + err.Error())
	}
}

// 获取AI对话历史
func GetAIChatHistory(c *lib.GinContext) error {
	var histories []model.AIChatHistory
	result := model.DB().Order("created_at desc").Limit(20).Find(&histories)
	if result.Error != nil {
		c.Logger().Error("查询对话历史失败: " + result.Error.Error())
		return response.JsonFail(c, "查询失败")
	}

	return response.JsonOk(c, histories, "查询成功")
}
